from app.schemas.flight_event import *
import requests
from reportlab.lib.pagesizes import A4
from reportlab.platypus import SimpleDocTemplate
from reportlab.lib.units import cm
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfbase import pdfmetrics
from reportlab.lib import colors
from PIL import Image as PILImage
from io import BytesIO
from utils.request import Request
from utils.upload import oss_upload
from loguru import logger
from reportlab.platypus import Table, TableStyle, Image, PageBreak


def report(patrol_detail: PatrolReport):
    # Register font from JSON input
    register_fonts('assets/fonts/MSYH.ttf')
    # Create PDF file, top margin set to 1 cm
    buffer = BytesIO()
    # buffer = 'test/patrol_report.pdf'
    pdf = SimpleDocTemplate(buffer,
                            pagesize=A4,
                            topMargin=1 * cm,
                            bottomMargin=1 * cm)
    # 主页和内页
    main_pages = create_main_page(patrol_detail)  # 现在返回多个页面

    pdf_elements = []
    pdf_elements.extend(main_pages)  # 添加所有主页元素
    pdf_elements.append(PageBreak())

    sub_table_elements = create_sub_page(patrol_detail)
    if sub_table_elements:
        for sub_table in sub_table_elements:
            pdf_elements.append(sub_table)
    # Build PDF
    pdf.build(pdf_elements)
    pdf_data = buffer.getvalue()
    buffer.close()
    upload_patrol_report(pdf_data, patrol_detail)


# Register the font
def register_fonts(font_path):

    pdfmetrics.registerFont(TTFont('MicrosoftYaHei', font_path))


# Resize image
def resize_image(image_url, target_width_cm):
    response = requests.get(image_url, verify=False)
    response.raise_for_status()  # 确保请求成功
    img = PILImage.open(BytesIO(response.content))
    aspect_ratio = img.height / img.width
    # 计算目标宽度和高度
    if img.width > img.height:
        target_height_cm = target_width_cm * aspect_ratio
        target_width = target_width_cm * cm
        target_height = target_width * aspect_ratio
    else:
        target_height_cm = target_width_cm
        target_width_cm = target_height_cm / aspect_ratio
        target_width = target_width_cm * cm
        target_height = target_height_cm * cm

    # 检查图片大小并压缩
    img_size = len(response.content)
    if img_size > 2 * 1024 * 1024:
        output = BytesIO()
        # 转换为RGB模式（如果是RGBA，去除透明通道）
        if img.mode in ('RGBA', 'P'):
            img = img.convert('RGB')
        # 压缩图片，quality范围1-95，值越小压缩率越高
        img.save(output, format='JPEG', quality=60)
        img_data = output
    else:
        img_data = BytesIO(response.content)
    # 创建 ReportLab 的 Image 对象
    return Image(img_data, width=target_width, height=target_height)


def create_main_page(detail: PatrolReport):
    # 每页显示的最大行数（标题占2行，所以实际数据行数要减2）
    rows_per_page = 20
    total_events = len(detail.event_defect_list)
    pages = []

    # 创建第一页（包含事件汇总等信息）
    first_page_data = [["事件汇总报告"],
                       [
                           "事件总数", "", detail.total_event_num, "统计时限", f"{detail.start_time} 至 {detail.end_time}",
                       ], ["事件等级"],
                       [
                           "危重", "", detail.event_level_count.danger, "紧急",
                           detail.event_level_count.urgent, "一般",
                           detail.event_level_count.normal
                       ], ["事件类型"], *[[
                           detail.event_type_count[i * 3].title if i * 3 < len(detail.event_type_count) else "", "",
                           detail.event_type_count[i * 3].num if i * 3 < len(detail.event_type_count) else "",
                           detail.event_type_count[i * 3 + 1].title if i * 3 + 1 < len(detail.event_type_count) else "",
                           detail.event_type_count[i * 3 + 1].num if i * 3 + 1 < len(detail.event_type_count) else "",
                           detail.event_type_count[i * 3 + 2].title if i * 3 + 2 < len(detail.event_type_count) else "",
                           detail.event_type_count[i * 3 + 2].num if i * 3 + 2 < len(detail.event_type_count) else ""
                       ] for i in range(3)], ["事件列表"]]

    # 添加表头和第一页的数据
    header = ["序号", "事件等级", "事件类型", "事件数量", "标注来源", "标注时间", "事件位置"]
    first_page_data.append(header)

    # 计算第一页可以显示的行数
    first_page_rows = min(rows_per_page - len(first_page_data), total_events)
    first_page_events = [[
        str(index + 1), event.level_text, event.event_target_text,
        event.event_num, event.simple_source_text, event.label_time, event.location
    ] for index, event in enumerate(detail.event_defect_list[:first_page_rows])
                         ]
    first_page_data.extend(first_page_events)

    # Define table styles
    row_heights = [
        None, 1 * cm, None, 1 * cm, None, 1 * cm, 1 * cm, 1 * cm, None, 1 * cm
    ]
    # 计算需要追加的行数（实际数据行数减去已有的行高数）
    remaining_rows = len(first_page_data) - len(row_heights)
    if remaining_rows > 0:
        row_heights.extend([1 * cm] * remaining_rows)
    # 创建第一页表格
    first_page = Table(first_page_data,
                       colWidths=[1 * cm, 2 * cm, 3 * cm, 3 * cm, 3 * cm],
                       rowHeights=row_heights)
    first_page.setStyle(
        TableStyle([
            ('SPAN', (0, 0), (-1, 0)),  # 合并第一行所有列
            ('SPAN', (0, 2), (-1, 2)),  # 合并第三行所有列
            ('LEADING', (0, 0), (-1, 0), 22),  # 设置第一行的行高为22
            ('ALIGN', (0, 0), (-1, 0), 'CENTER'),  # 第一行文字居中
            ('FONTSIZE', (0, 0), (-1, 0), 18),  # 第一行文字字号18
            ('BACKGROUND', (0, 0), (-1, 0), colors.HexColor('#E1EFD9')),  # 第一行为表头 背景色为浅绿
            ('SPAN', (0, 1), (1, 1)),  # 合并第2行1,2列
            # ('SPAN', (2, 1), (3, 1)),  # 合并第2行3,4列
            # ('SPAN', (5, 1), (6, 1)),  # 合并第2行6,7列
            ('SPAN', (4, 1), (6, 1)),  # 合并第2行后半段
            ('LEADING', (0, 2), (-1, 2), 22),  # 设置第三行的行高为22
            ('ALIGN', (0, 2), (-1, 2), 'CENTER'),  # 第三行文字居中
            ('FONTSIZE', (0, 2), (-1, 2), 18),  # 第三行文字字号18
            ('BACKGROUND', (0, 2), (-1, 2), colors.HexColor('#E1EFD9')),  # 第三行背景色为浅绿
            ('LEADING', (0, 4), (-1, 4), 22),  # 设置第五行的行高为22
            ('ALIGN', (0, 4), (-1, 4), 'CENTER'),  # 第五行文字居中
            ('FONTSIZE', (0, 4), (-1, 4), 18),  # 第五行文字字号18
            ('BACKGROUND', (0, 4), (-1, 4), colors.HexColor('#E1EFD9')),  # 第五行背景色为浅绿
            ('SPAN', (0, 8), (-1, 8)),  # 合并第八行所有列
            ('LEADING', (0, 8), (-1, 8), 22),  # 设置第八行的行高为22
            ('ALIGN', (0, 8), (-1, 8), 'CENTER'),  # 第八行文字居中
            ('FONTSIZE', (0, 8), (-1, 8), 18),  # 第八行文字字号18
            ('BACKGROUND', (0, 8), (-1, 8), colors.HexColor('#E1EFD9')),  # 第八行背景色为浅绿
            ('SPAN', (0, 3), (1, 3)),  # 合并第四行1,2列
            ('SPAN', (0, 4), (-1, 4)),  # 合并第五行所有列
            ('SPAN', (0, 5), (1, 5)),  # 合并第六行1,2列
            ('SPAN', (0, 6), (1, 6)),  # 合并第七行1,2列
            ('SPAN', (0, 7), (1, 7)),  # 合并第八行1,2列
            # ('LEADING', (0, 5), (-1, 5), 15), # 说明部分 行高
            ('ALIGN', (0, 6), (-1, 6), 'CENTER'),  # 图片显示居中
            # ('BACKGROUND', (1, 1), (-1, -1), colors.white), # 除了第1行其他的背景都为白色
            ('TEXTCOLOR', (0, 0), (-1, -1), colors.black),  # 所有的字的颜色为黑色
            # ('LEADING', (0, 1), (-1, 3), 13), # 除了第1行至第4行 行高为12
            # ('ALIGN', (0, 1), (-1, 4), 'LEFT'), # 除了第1行 他行的行为左对齐
            # ('ALIGN', (0, 1), (-1, 4), 'LEFT'), # 除了第1行 他行的行为左对齐
            # ('ALIGN', (0, 6), (-1, -1), 'LEFT'), # 除了第1行 他行的行为左对齐
            ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),  # 所有行高度居中
            # ('VALIGN', (0, 5), (-1, -1), 'TOP'), # 所有行高度居中
            ('ALIGN', (0, 0), (-1, -1), 'CENTER'),  # 第三行文字居中
            # ('ALIGN', (3, 6), (5, 6), 'RIGHT'), # 除了第1行 他行的行为左对齐
            # ('ALIGN', (3, 7), (5, 7), 'RIGHT'), # 除了第1行 他行的行为左对齐
            ('FONTNAME', (0, 0), (-1, -1), 'MicrosoftYaHei'),  # 所有字体为微软雅黑
            ('GRID', (0, 0), (-1, -1), 1, colors.black),  # 绘制所有框线
        ]))
    pages.append(first_page)

    # 如果还有更多数据，创建后续页面
    if total_events > first_page_rows:
        remaining_events = detail.event_defect_list[first_page_rows:]
        for i in range(0, len(remaining_events), rows_per_page):
            page_events = remaining_events[i:i + rows_per_page]
            page_data = [header]  # 每页都添加表头
            page_data.extend([[
                str(index + first_page_rows + i + 1), event.level_text, event.event_target_text,
                event.target_num, event.simple_source_text, event.label_time, event.location
            ] for index, event in enumerate(page_events)])

            # 创建新页面的表格
            subsequent_page_heights = [1 * cm] * len(page_data)
            page_table = Table(
                page_data,
                colWidths=[1 * cm, 2 * cm, 3 * cm, 3 * cm, 3 * cm],
                rowHeights=subsequent_page_heights)
            page_table.setStyle(
                TableStyle([
                    ('TEXTCOLOR', (0, 0), (-1, -1),
                     colors.black),  # 所有的字的颜色为黑色
                    ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),  # 所有行高度居中
                    ('ALIGN', (0, 0), (-1, -1), 'CENTER'),  # 第三行文字居中
                    ('FONTNAME', (0, 0), (-1, -1), 'MicrosoftYaHei'),  # 所有字体为微软雅黑
                    ('GRID', (0, 0), (-1, -1), 1, colors.black),  # 绘制所有框线
                ]))
            pages.append(PageBreak())
            pages.append(page_table)

    return pages


def create_sub_page(detail: PatrolReport):
    sub_table_page = []

    # 统一为6列结构并添加图片行（修正事件缺陷列表访问方式）
    for event_defect in detail.event_defect_list:
        sub_element = [
            [event_defect.title, "", "", "", "", ""],
            [
                "飞行任务", event_defect.flight_record_name, "", "", "", ""
            ],
            [
                "事件类型", event_defect.event_target_text, "", "拍摄时间",
                event_defect.shoot_time, ""
            ],
            [
                '事件数量', event_defect.event_num,
                "事件等级", event_defect.level_text,
                "处理状态", event_defect.process_status
            ],
            ["标注来源", event_defect.source_text],  # 第4行：6列
            ["事件位置", event_defect.location + '(' + event_defect.coordinate + ')'],  # 第5行：6列
            ["事件说明", event_defect.remark],  # 第6行：6列
            ["事件图片", resize_image(event_defect.defect_img_url,
                                  14.5)]  # 第7行：6列（直接使用resize_image返回的图片对象）
        ]
        # for img_arr in img_list:
        #         sub_element.append(img_arr)
        sub_table = Table(
            sub_element,
            colWidths=[3 * cm, 2 * cm, 4 * cm, 3 * cm, 2 * cm, 4 * cm],
            rowHeights=[
                None, 1 * cm, 1 * cm, 1 * cm, 1 * cm, 1 * cm, 2 * cm, 18 * cm
            ])
        sub_table.setStyle(
            TableStyle([
                ('SPAN', (0, 0), (-1, 0)),  # 合并第一行所有列
                ('LEADING', (0, 0), (-1, 0), 22),  # 设置第一行的行高为22
                ('ALIGN', (0, 0), (-1, 0), 'CENTER'),  # 第一行文字居中
                ('FONTSIZE', (0, 0), (-1, 0), 18),  # 第一行文字字号18
                ('BACKGROUND', (0, 0), (-1, 0), colors.HexColor('#E1EFD9')),  # 第一行为表头 背景色为浅绿
                ('SPAN', (1, 1), (-1, 1)),  # 合并第2第一列外所有列
                ('SPAN', (1, 2), (2, 2)),  # 合并第3行2,3列
                ('SPAN', (4, 2), (5, 2)),  # 合并第3行5,6列
                ('ALIGN', (0, 3), (-1, 3), 'LEFT'),
                ('SPAN', (1, 4), (-1, 4)),  # 合并第5行第一列外所有列
                ('SPAN', (1, 5), (-1, 5)),  # 合并第6行第一列外所有列
                ('SPAN', (1, 6), (-1, 6)),  # 合并第7行除第一列外所有列
                ('SPAN', (1, 7), (-1, 7)),  # 合并第8行所有列
                ('SPAN', (0, 8), (-1, 8)),  # 合并第9行所有列
                ('LEADING', (0, 3), (-1, 3), 15),  # 说明部分 行高为
                ('ALIGN', (0, 4), (-1, 5), 'CENTER'),  # 图片显示居中
                ('BACKGROUND', (1, 1), (-1, -1),
                 colors.white),  # 除了第1行其他的背景都为白色
                ('TEXTCOLOR', (0, 0), (-1, -1), colors.black),  # 所有的字的颜色为黑色
                ('ALIGN', (1, 4), (-1, 6), 'LEFT'),
                # ('LEADING', (0, 1), (-1, 3), 13), # 除了第1行至第4行 行高为12
                # ('ALIGN', (0, 1), (-1, 3), 'LEFT'), # 除了第1行 他行的行为左对齐
                ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),  # 所有行高度居中
                ('VALIGN', (1, 7), (1, 7), 'TOP'),  # 第七行第二列顶部对齐
                ('FONTNAME', (0, 0), (-1, -1), 'MicrosoftYaHei'),  # 所有字体为微软雅黑
                ('GRID', (0, 0), (-1, 10), 1, colors.black),  # 绘制所有框线
                # ('LINEBELOW', (0, 5), (-1, 5), 1, colors.black), # 为图片行设置下边框
                # ('LINEBEFORE', (0, 4), (0, 5), 1, colors.black), # 给图片行设置左边框线
                # ('LINEAFTER', (-1, 4), (-1, 5), 1, colors.black), # 给图片行设置右边框线
                ('LEFTPADDING', (0, 0), (-1, -1), 5),  # 所有行左侧留白5
                ('ALIGN', (1, 4), (-1, 6), 'LEFT'),
                ('BOTTOMPADDING', (0, 0), (-1, -1), 5),  # 所有行底部留白5
                ('TOPPADDING', (0, 0), (-1, -1), 5),  # 所有行顶侧留白5
                ('FONTSIZE', (0, 1), (-1, -1), 10),  # 除了第1行其他的字号为10
                ('ALIGN', (0, 0), (-1, 3), 'CENTER'),
                ('ALIGN', (0, 6), (0, 6), 'CENTER'),
                ('ALIGN', (0, 7), (-1, 7), 'CENTER'),
            ]))
        # 添加到结果列表
        sub_table_page.append(sub_table)

        # 添加分页符（除最后一个表格外）
        if event_defect != detail.event_defect_list[-1]:
            sub_table_page.append(PageBreak())

    return sub_table_page


def upload_patrol_report(pdf_data, report: PatrolReport):
    upload = oss_upload(report.oss_config)
    data = None
    res = upload(f'{report.source_id}.pdf', pdf_data)
    if res:
        object_key = res
        data = {
            'sourceId': report.source_id,
            'sourceType': report.source_type,
            'objectKey': object_key
        }
        logger.info(f'[patrol_report]上传oss成功')
        Request.callback_result(data, url=report.upload_callback_url)
